const defaultParagraphSeparatorString = 'defaultParagraphSeparator'
const formatBlock = 'formatBlock'
// eslint-disable-next-line max-len
const addEventListener = (parent: HTMLElement, type: string, listener: any) => parent.addEventListener(type, listener)
const appendChild = (parent: HTMLElement, child: HTMLElement) => parent.appendChild(child)
const createElement = (tag: string) => document.createElement(tag)
const queryCommandState = (command: string) => document.queryCommandState(command)
const queryCommandValue = (command: string) => document.queryCommandValue(command)

// eslint-disable-next-line max-len
export const exec = (command: string, value?: string) => document.execCommand(command, false, value)

const defaultClasses = {
  actionbar: 'pell-actionbar',
  button: 'pell-button',
  content: 'pell-content',
  selected: 'pell-button-selected',
}

export const init = (settings: SettingOptions) => {
  const classes = { ...defaultClasses, ...settings.classes }

  const defaultParagraphSeparator = settings[defaultParagraphSeparatorString] || 'div'

  const content = settings.element.content = createElement('div')
  content.contentEditable = 'true'
  content.className = classes.content
  // @ts-ignore
  content.oninput = ({ target: { firstChild } }) => {
    if (firstChild && firstChild.nodeType === 3) exec(formatBlock, `<${defaultParagraphSeparator}>`)
    else if (content.innerHTML === '<br>') content.innerHTML = ''
    settings.onChange && settings.onChange(content.innerHTML)
  }
  content.onkeydown = event => {
    if (settings.onKeydown && settings.onKeydown(event)) {
      return false
    }
    if (event.key === 'Enter' && queryCommandValue(formatBlock) === 'blockquote') {
      setTimeout(() => exec(formatBlock, `<${defaultParagraphSeparator}>`), 0)
    }
  }
  appendChild(settings.element, content)

  if (settings.styleWithCSS) exec('styleWithCSS')
  exec(defaultParagraphSeparatorString, defaultParagraphSeparator)

  return settings.element
}

export default { exec, init }

interface SettingOptions {
  element: HTMLElement & {
    content: HTMLElement
  }
  classes?: {content: string}
  defaultParagraphSeparator?: string
  styleWithCSS?: boolean
  onChange?: (html: string) => void
  onKeydown?: (e: KeyboardEvent) => boolean
}
